package com.db.logging;

import java.io.*;
import java.util.Date;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

/**
 * @author nulls.narik
 */
public class MyFileLogger extends AbstractLogger {

    private final BlockingQueue<String> messages;

    private final PrintWriter writer;

    private final Thread asyncWrite = new Thread(new Runnable() {
        @Override
        public void run() {
            try {
                while (true) {
                    while (messages.isEmpty());

                    writer.println(messages.take());
                    writer.flush();
                }
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            } catch (Throwable e) {
                System.out.println("Error while work async logger");
            }
        }
    });

    private final Level level;

    protected MyFileLogger(String name, Level level) throws FileNotFoundException {
        super(name);

        this.level = level;
        writer = new PrintWriter(new FileOutputStream(new File(name + ".log"), true));
        messages = new LinkedBlockingQueue<String>();
        asyncWrite.setDaemon(true);
        asyncWrite.start();
    }

    @Override
    public boolean isDebugEnabled() {
        return level.compareTo(Level.DEBUG) <= 0;
    }

    protected enum Level {
        DEBUG,
        INFO,
        ERROR;


    }

    private String getMessage(Level level, String s) {
        return String.format("%s. Thread: %s. %s\n%s", level.toString(), Thread.currentThread().getName(), new Date(), s);
    }

    private String getMessage(Level level, String s, Object... objects) {
        return String.format("%s. Thread: %s. %s\n%s", level.toString(), Thread.currentThread().getName(), new Date(), String.format(s, objects));
    }

    @Override
    public void debug(String s) {
        if (isDebugEnabled()) {
            String message = getMessage(Level.DEBUG, s);
            while (!messages.offer(message));
        }
    }

    @Override
    public void debug(String s, Object o) {
        if (isDebugEnabled()) {
            String message = getMessage(Level.DEBUG, s, o);
            while (!messages.offer(message));
        }
    }

    @Override
    public void debug(String s, Object o, Object o2) {
        if (isDebugEnabled()) {
            String message = getMessage(Level.DEBUG, s, o, o2);
            while (!messages.offer(message));
        }
    }

    @Override
    public void debug(String s, Object... objects) {
        if (isDebugEnabled()) {
            String message = getMessage(Level.DEBUG, s, objects);
            while (!messages.offer(message));
        }
    }

    @Override
    public boolean isInfoEnabled() {
        return level.compareTo(Level.INFO) <= 0;
    }

    @Override
    public void info(String s) {
        if (isInfoEnabled()) {
            String message = getMessage(Level.INFO, s);
            while (!messages.offer(message));
        }
    }

    @Override
    public void info(String s, Object o) {
        if (isInfoEnabled()) {
            String message = getMessage(Level.INFO, s, o);
            while (!messages.offer(message));
        }
    }

    @Override
    public void info(String s, Object o, Object o2) {
        if (isInfoEnabled()) {
            String message = getMessage(Level.INFO, s, o, o2);
            while (!messages.offer(message));
        }
    }

    @Override
    public void info(String s, Object... objects) {
        if (isInfoEnabled()) {
            String message = getMessage(Level.INFO, s, objects);
            while (!messages.offer(message));
        }
    }

    @Override
    public boolean isErrorEnabled() {
        return level.compareTo(Level.ERROR) <= 0;
    }

    @Override
    public void error(String s) {
        if (isErrorEnabled()) {
            String message = getMessage(Level.ERROR, s);
            while (!messages.offer(message));
        }
    }

    @Override
    public void error(String s, Object o) {
        if (isErrorEnabled()) {
            String message = getMessage(Level.ERROR, s, o);
            while (!messages.offer(message));
        }
    }

    @Override
    public void error(String s, Object o, Object o2) {
        if (isErrorEnabled()) {
            String message = getMessage(Level.ERROR, s, o, o2);
            while (!messages.offer(message));
        }
    }

    @Override
    public void error(String s, Object... objects) {
        if (isErrorEnabled()) {
            String message = getMessage(Level.ERROR, s, objects);
            while (!messages.offer(message));
        }
    }
}
